#=======================================================================
#				Serial Killer Roguelike	v 0.0.3
#=======================================================================
#parse command line there

#from time import time
import sys, time, getopt
#from time import gmtime, strftime

import libtcodpy as libtcod

try:
	
    import psyco
    psyco.full()

except ImportError:
    pass




import config
#-----------------------------------------------------------------------
args = sys.argv[1:]
opts, args = getopt.getopt(args, "ds:")

for o, _arg in opts:
	if o in ("-d", "--dev"):		
		config.__PYSKILLER_DEBUG = True
		
	if o in ("-s", "--seed"):		
		config.__PYSKILLER_SEED = int(_arg)
		
	if o in ("-t", "--time"):		
		config.__PYSKILLER_RND_TIME = True
#-----------------------------------------------------------------------



import ent
import sk_map, sk_time, sk_input, viewport, fov
import render
import events
import law
import combat, bodysim
import ai, pathfinder, player


SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50

MAP_WIDTH 	= 80
MAP_HEIGHT  = 80

FOV_ALGO = 0  #default FOV algorithm
FOV_LIGHT_WALLS = True
TORCH_RADIUS = 20

viewport = viewport.Viewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-6)
render = render.Render(SCREEN_WIDTH,SCREEN_HEIGHT)
con = render.con

game_state = 'playing'
player_action = None

playerx = SCREEN_WIDTH/2
playery = SCREEN_HEIGHT/2

game_map = sk_map.Map(MAP_WIDTH,MAP_HEIGHT)
fov_map = libtcod.map_new(100, 100)

viewport.con = con
render.set_viewport(viewport)

objects = []


#fixme later
em = events.EventManager(con,game_map,viewport)

em.register("map",game_map)
em.register("objects",objects)
em.register("fov_map",fov_map)
em.register("fov",fov.Fov())
em.register("render",render)
#em.register("viewport",viewport)

timer = sk_time.sk_timer()
em.register("sk_time",timer)

game_map.em = em
game_map.build_map(con)	#now build map and place player inside of safehouse


player = 	player.PlayerEnt(em, 20, 20, '@', libtcod.white)
player.set_combat(combat.PlayerCombat())
player.set_body(bodysim.BodySimulation())
em.register("player",player)

player.spawn()
game_map.place_player(player)

objects.append(player)
#player.spawn()	#?

viewport.locate(player.x,player.y)

#=======================================================================
social = law.SocialController()
em.register("social",social)

render.message("Wellcome to the Serial Killer Roguelike!")
render.message("Press 'wsad' to move, 'space' to skip turn")
render.message("Press 'tab' to open your character screen")


em.services["fov"].fov_map = fov_map

__TIMER = None

def timer_push():
	global __TIMER
	__TIMER = time.time()
		
def timer_pop(msg):
	#global TIMER
	print msg + " in " + str(time.time()-__TIMER) + " seconds"
	timer_push()


import cProfile

def render_all():
	
	#timer_push()
	
	if player.fow_outdated:
		player.fow_outdated = False
		em.services["fov"].recompute(player)
		
	#timer_pop("fov.recompute()")
	#import psyco
	#psyco.bind(render.render_map)
	#g(args)
	#cProfile.run('render.render_map(game_map, em.services["fov"].fov_map)')
	render.render_map(game_map, em.services["fov"].fov_map)
	#timer_pop("render.render_map()")

	render.render_objects()			
	#timer_pop("render.render_objects()")
	
	render.draw_object(player)
	#timer_pop("render.draw_object()")
	
	#exit()
	
#psyco.bind(render_all)
	

TURN = 0
render.message("Building path nodes, please wait...");
#TODO: draw "loading" line
#=======================================================================
input_controller = sk_input.InputController()
em.register("input",input_controller)

_pfinder = pathfinder.Pathfinder()
#_pfinder.em = em
em.register("pathfinder",_pfinder)
_pfinder.start()

def think():
	for object in objects:
			if object != player:
				object.think()
		
	player.think()

while not libtcod.console_is_window_closed():
	#libtcod.console_set_default_foreground(con, libtcod.white)
	
	ts_start = time.time()
	render_all()

	#TODO: move to render.GUI_Timer
	timer = em.services["sk_time"]
	if timer:
		libtcod.console_set_default_foreground(con, libtcod.white)
		#libtcod.console_print_left(con, SCREEN_WIDTH-20, 1, libtcod.BKGND_NONE,
		libtcod.console_print_ex(con, SCREEN_WIDTH-20, 1, libtcod.BKGND_NONE, libtcod.LEFT,
				timer.get_time().strftime("%d/%m/%Y - %H:%M"))
	
	#render.render_debug() #DEBUG DEBUG DEBUG
	
	libtcod.console_set_default_foreground(0, libtcod.white)
	libtcod.console_print_ex(con, 1, 1,
		libtcod.BKGND_NONE, libtcod.LEFT, '%3d FPS' % libtcod.sys_get_fps())
		
	libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
	
	#render GUI overlay after we rendered gui shit
	render.render_GUI()
	libtcod.console_flush()
		
	player_action = input_controller.handle_keys()
	
	#player_action = handle_keys()
	if player_action == 'exit':
		break
	#make world's turn before player's turn to calculate routes, etcetra
	if TURN == 0:
		player_action = 'take-turn'
		ai.AI_MAX_TURN_LEN = 20

	else:
		ai.AI_MAX_TURN_LEN = 1
	
	if game_state == 'playing' and player_action != 'didnt-take-turn':
		#=============== WORLD TURN START ==================
		
		ai.AI_TURN_LEN = 0	#reset patfinder timer
		
		#cProfile.run('think()')
		think()
		
				
		ts_end = time.time()
		print "turn %d time: %f seconds" % (TURN, ts_end-ts_start)
		
		
		if TURN == 0:
			render.message("done in " + str(round(ts_end-ts_start)) + " seconds");
			
		TURN += 1
		
		em.services["sk_time"].tick()
		
		
				
		render.clear_all()
		#===================== TURN END =====================
